<template>
  <div class="p-4">
    <h2 class="text-2xl font-bold mb-4 text-gray-800 dark:text-gray-200">图片压缩</h2>

    <!-- 上传区域 -->
    <div
      class="mb-6 relative"
      @dragover.prevent="isDragging = true"
      @dragleave.prevent="isDragging = false"
      @drop.prevent="handleDrop"
    >
      <input
        ref="fileInput"
        type="file"
        accept="image/*"
        multiple
        class="hidden"
        @change="handleFileSelect"
      >
      
      <div
        class="min-h-[200px] border-2 border-dashed rounded-lg flex flex-col items-center justify-center p-6"
        :class="[
          isDragging
            ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20'
            : 'border-gray-300 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500'
        ]"
        @click="$refs.fileInput.click()"
      >
        <div class="text-center">
          <svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none" viewBox="0 0 48 48">
            <path
              d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
          </svg>
          <p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
            点击或拖拽图片到此处
          </p>
          <p class="mt-1 text-xs text-gray-500 dark:text-gray-500">
            支持 PNG, JPG, WEBP 格式
          </p>
        </div>
      </div>
    </div>

    <!-- 压缩选项 -->
    <div v-if="images.length > 0" class="mb-6 bg-white dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
      <h3 class="text-lg font-semibold mb-4 text-gray-800 dark:text-gray-200">压缩选项</h3>
      <div class="space-y-4">
        <div>
          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
            质量 ({{ quality }}%)
          </label>
          <input
            v-model="quality"
            type="range"
            min="1"
            max="100"
            class="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer"
          >
        </div>
        <div>
          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
            最大宽度 ({{ maxWidth }}px)
          </label>
          <input
            v-model="maxWidth"
            type="range"
            min="100"
            max="4096"
            step="100"
            class="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer"
          >
        </div>
        <div class="flex items-center">
          <input
            v-model="preserveFormat"
            type="checkbox"
            class="h-4 w-4 text-blue-500 focus:ring-blue-500 border-gray-300 rounded"
          >
          <label class="ml-2 text-sm text-gray-700 dark:text-gray-300">
            保持原始格式
          </label>
        </div>
      </div>
    </div>

    <!-- 图片列表 -->
    <div v-if="images.length > 0" class="space-y-4">
      <div
        v-for="(image, index) in images"
        :key="index"
        class="bg-white dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700"
      >
        <div class="flex flex-col md:flex-row gap-4">
          <!-- 预览 -->
          <div class="w-full md:w-1/2 space-y-2">
            <h4 class="text-sm font-medium text-gray-700 dark:text-gray-300">原始图片</h4>
            <img
              :src="image.originalUrl"
              :alt="image.file.name"
              class="max-w-full h-auto rounded"
            >
            <div class="text-sm text-gray-500">
              {{ formatFileSize(image.file.size) }}
            </div>
          </div>

          <!-- 压缩后 -->
          <div v-if="image.compressedUrl" class="w-full md:w-1/2 space-y-2">
            <h4 class="text-sm font-medium text-gray-700 dark:text-gray-300">压缩后</h4>
            <img
              :src="image.compressedUrl"
              :alt="image.file.name"
              class="max-w-full h-auto rounded"
            >
            <div class="text-sm text-gray-500">
              {{ formatFileSize(image.compressedSize) }}
              (节省 {{ calculateSavings(image) }}%)
            </div>
            <button
              @click="downloadImage(image)"
              class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
            >
              下载
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'

interface ImageItem {
  file: File
  originalUrl: string
  compressedUrl?: string
  compressedSize: number
}

const fileInput = ref<HTMLInputElement | null>(null)
const isDragging = ref(false)
const images = ref<ImageItem[]>([])
const quality = ref(80)
const maxWidth = ref(1920)
const preserveFormat = ref(false)

// 处理文件选择
const handleFileSelect = (event: Event) => {
  const input = event.target as HTMLInputElement
  if (input.files) {
    addFiles(Array.from(input.files))
  }
}

// 处理拖放
const handleDrop = (event: DragEvent) => {
  isDragging.value = false
  if (event.dataTransfer?.files) {
    addFiles(Array.from(event.dataTransfer.files))
  }
}

// 添加文件
const addFiles = (files: File[]) => {
  const imageFiles = files.filter(file => file.type.startsWith('image/'))
  
  imageFiles.forEach(file => {
    const reader = new FileReader()
    reader.onload = (e) => {
      if (typeof e.target?.result === 'string') {
        images.value.push({
          file,
          originalUrl: e.target.result,
          compressedSize: 0
        })
      }
    }
    reader.readAsDataURL(file)
  })
}

// 压缩图片
const compressImage = async (image: ImageItem) => {
  return new Promise<void>((resolve) => {
    const img = new Image()
    img.src = image.originalUrl
    
    img.onload = () => {
      const canvas = document.createElement('canvas')
      let width = img.width
      let height = img.height

      // 调整尺寸
      if (width > maxWidth.value) {
        height = (height * maxWidth.value) / width
        width = maxWidth.value
      }

      canvas.width = width
      canvas.height = height

      const ctx = canvas.getContext('2d')
      if (!ctx) return

      ctx.drawImage(img, 0, 0, width, height)

      // 确定输出格式
      const format = preserveFormat.value
        ? image.file.type
        : 'image/webp'

      // 压缩
      const compressedUrl = canvas.toDataURL(format, quality.value / 100)
      
      // 计算压缩后的大小
      const base64str = compressedUrl.split(',')[1]
      const compressedSize = Math.round((base64str.length * 3) / 4)

      // 更新图片对象
      image.compressedUrl = compressedUrl
      image.compressedSize = compressedSize

      resolve()
    }
  })
}

// 监听压缩选项变化
watch([quality, maxWidth, preserveFormat], async () => {
  for (const image of images.value) {
    await compressImage(image)
  }
})

// 下载压缩后的图片
const downloadImage = (image: ImageItem) => {
  if (!image.compressedUrl) return

  const link = document.createElement('a')
  link.href = image.compressedUrl
  link.download = `compressed_${image.file.name}`
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

// 格式化文件大小
const formatFileSize = (bytes: number) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`
}

// 计算节省空间百分比
const calculateSavings = (image: ImageItem) => {
  if (!image.compressedSize) return 0
  const savings = ((image.file.size - image.compressedSize) / image.file.size) * 100
  return Math.round(savings)
}
</script> 